bd2e77b2bc4024bc4699c0ba0190c69ec16e6dee,elda-lda/src/main/java/com/epimorphics/lda/restlets/RouterRestlet.java,RouterRestlet,runEndpoint,#Controls#String#number#ServletContext#HttpServletRequest#HttpServletResponse#UriInfo#MultiMap#List#String#Match#,344

Before Change


    	Bindings forErrorHandling = null;
    	URLforResource as = pathAsURLFactory(servCon);
    	URI requestUri = ui.getRequestUri();
    	ELog.debug(log, "handling request '%s'", requestUri );
    //
        try {
        	URI ru = makeRequestURI(ui, match, requestUri);
        	APIEndpoint ep = match.getEndpoint();
        	boolean needsVaryAccept = formatName == null && queryParams.containsKey( "_format" ) == false;
        	
        	Renderer _default = APIEndpointUtil.getRenderer( ep, formatName, mediaTypes );
        	
        	if (formatName == null && _default != null) formatName = _default.getPreferredSuffix();
        	
        	Renderer r = APIEndpointUtil.getRenderer( ep, formatName, mediaTypes );    	
        	
        	if (r == null) {
        		String message = formatName == null
        			? "no suitable media type was provided for rendering."
        			: "renderer '" + formatName + "' is not known to this server."
        			;
        		return standardHeaders( null, Response.status( Status.BAD_REQUEST )
        			.entity( Messages.niceMessage( message ) ) )
        			.build()
        			;
        	} 
        //        	
        	Bindings b = ep.getSpec().getBindings().copy();
        	
        	String _properties = queryParams.getOne("_properties");
			b.put("_properties", _properties == null ? "" : _properties );
			
			String _page = queryParams.getOne("_page");
			b.put("_page", _page == null ? "" : _page );
			
			String _view = queryParams.getOne("_view");
			b.put("_view", _view == null ? "" : _view );
			
			b.putAny("_servletRequest", servletRequest);
			b.putAny("_servletResponse", servletResponse);
						
			forErrorHandling = new Bindings(b, as);
			        
			List<String> formatNames = match.getEndpoint().getSpec().getRendererFactoryTable().formatNames();
			
        	APIEndpoint.Request req =
        		new APIEndpoint.Request( c, ru, b )
        		.withFormats( formatNames, formatName )
        		.withMode( r.getMode() )
        		;
        	
        	ModelPrefixEditor mpe = ep.getSpec().getAPISpec().getModelPrefixEditor();
        //
        	NoteBoard nb = new NoteBoard();
        	ResponseResult resultsAndBindings = APIEndpointUtil.call( req, nb, match, contextPath, queryParams );
        //	
        	boolean notFoundIfEmpty = b.getAsString( "_exceptionIfEmpty", "yes" ).equals( "yes" );
        //
        	if (ep.getSpec().isItemEndpoint() && notFoundIfEmpty && resultsAndBindings.resultSet.isEmpty()) {
        		ELog.debug(log, "resultSet is empty, returning status 404.");   
        		boolean passOnIfMissing = b.getAsString( "_passOnIfEmpty", "no" ).equals( "yes" );
				if (passOnIfMissing) throw new NotFoundException();
				return Response.status( Status.NOT_FOUND )
					.type( "text/plain" )
					.header( ACCESS_CONTROL_ALLOW_ORIGIN, "*" )
					.header( VARY, "Accept" )
					.entity( "404 Resource Not Found\n\n" + ru + "\n")
					.build()
					;
			}       	
        //
        	Map<String, String> termBindings = mpe.rename( resultsAndBindings.uriToShortnameMap );
            APIResultSet results = resultsAndBindings.resultSet.applyEdits( mpe );
			Bindings rc = new Bindings( resultsAndBindings.bindings.copy(), as );
		//	
        	if (_default.getPreferredSuffix().equals( r.getPreferredSuffix())) {
        		MediaType dmt = _default.getMediaType(rc);
        		if (!dmt.equals(r.getMediaType(rc))) {
        			r = RouterRestletSupport.changeMediaType( r, dmt );
        		}
        	}
        	
        	long expiresAt = nb.expiresAt;  
        	
//        	System.err.println( ">> expiresAt: " + RouterRestletSupport.expiresAtAsRFC1123(expiresAt));
//        	System.err.println( ">> expiresAt: (= " + expiresAt + ")" );
//        	System.err.println( ">>  " + (expiresAt < System.currentTimeMillis() ? " expired" : " still alive" ) + ".");
        	
        	String expiresDate = expiresAt < System.currentTimeMillis() 
        		? NO_EXPIRY 
        		: RouterRestletSupport.expiresAtAsRFC1123(expiresAt)
        		;
						
        	URI contentLocation = req.getURIwithFormat();
        	
			MediaType mt = r.getMediaType(rc);
			ELog.debug(log, "rendering with formatter '%s'", mt );
			Times times = c.times;
			Renderer.BytesOut bo = r.render( times, rc, termBindings, results );
			int mainHash = runHash + ru.toString().hashCode();
			return returnAs( contentLocation, expiresDate, results, mainHash + mt.hashCode(), wrap(times, bo), needsVaryAccept, mt );
	//
        } catch (StackOverflowError e) {
        	StatsValues.endpointException();
            log.error("Stack Overflow Error" );
            if (log.isDebugEnabled()) ELog.debug(log, "%s", Messages.shortStackTrace( e ) );
            String message = Messages.niceMessage("Stack overflow", e.getMessage() );
            return ErrorPages.respond(forErrorHandling, servCon, "stack_overflow", message, EldaException.SERVER_ERROR);
        
        } catch (VelocityRenderingException e) {
            return ErrorPages.respond(forErrorHandling, servCon, "velocity_rendering", e.getMessage(), EldaException.SERVER_ERROR); 
        
        } catch (BadRequestException e) {
        	return ErrorPages.respond(forErrorHandling, servCon, "bad_request", e.getMessage(), EldaException.BAD_REQUEST);
                    	
        } catch (UnknownShortnameException e) {
        	ELog.error(log, "UnknownShortnameException: " + e.getMessage() );
            if (log.isDebugEnabled()) ELog.debug(log, "%s", Messages.shortStackTrace( e ));
        	StatsValues.endpointException();
        	return ErrorPages.respond(forErrorHandling, servCon, "unknown_shortname", e.getMessage(), EldaException.BAD_REQUEST); 
        
        } catch (EldaException e) {
        	StatsValues.endpointException();
        	ELog.error(log, "Exception: " + e.getMessage() );
        	if (log.isDebugEnabled()) ELog.debug(log, "%s", Messages.shortStackTrace( e ));
        	return ErrorPages.respond(forErrorHandling, servCon, "exception", e.getMessage(), EldaException.SERVER_ERROR);
        
        } catch (NotFoundException e) {

After Change


    	String formatName = initialFormatName;
    	Bindings forErrorHandling = null;
    	URLforResource as = pathAsURLFactory(servCon);
    	URI requestUri = ui.getRequestUri();
    	log.debug(ELog.message("handling request '%s'", requestUri ));
    //
        try {
        	URI ru = makeRequestURI(ui, match, requestUri);
        	APIEndpoint ep = match.getEndpoint();
        	boolean needsVaryAccept = formatName == null && queryParams.containsKey( "_format" ) == false;
        	
        	Renderer _default = APIEndpointUtil.getRenderer( ep, formatName, mediaTypes );
        	
        	if (formatName == null && _default != null) formatName = _default.getPreferredSuffix();
        	
        	Renderer r = APIEndpointUtil.getRenderer( ep, formatName, mediaTypes );    	
        	
        	if (r == null) {
        		String message = formatName == null
        			? "no suitable media type was provided for rendering."
        			: "renderer '" + formatName + "' is not known to this server."
        			;
        		return standardHeaders( null, Response.status( Status.BAD_REQUEST )
        			.entity( Messages.niceMessage( message ) ) )
        			.build()
        			;
        	} 
        //        	
        	Bindings b = ep.getSpec().getBindings().copy();
        	
        	String _properties = queryParams.getOne("_properties");
			b.put("_properties", _properties == null ? "" : _properties );
			
			String _page = queryParams.getOne("_page");
			b.put("_page", _page == null ? "" : _page );
			
			String _view = queryParams.getOne("_view");
			b.put("_view", _view == null ? "" : _view );
			
			b.putAny("_servletRequest", servletRequest);
			b.putAny("_servletResponse", servletResponse);
						
			forErrorHandling = new Bindings(b, as);
			        
			List<String> formatNames = match.getEndpoint().getSpec().getRendererFactoryTable().formatNames();
			
        	APIEndpoint.Request req =
        		new APIEndpoint.Request( c, ru, b )
        		.withFormats( formatNames, formatName )
        		.withMode( r.getMode() )
        		;
        	
        	ModelPrefixEditor mpe = ep.getSpec().getAPISpec().getModelPrefixEditor();
        //
        	NoteBoard nb = new NoteBoard();
        	ResponseResult resultsAndBindings = APIEndpointUtil.call( req, nb, match, contextPath, queryParams );
        //	
        	boolean notFoundIfEmpty = b.getAsString( "_exceptionIfEmpty", "yes" ).equals( "yes" );
        //
        	if (ep.getSpec().isItemEndpoint() && notFoundIfEmpty && resultsAndBindings.resultSet.isEmpty()) {
        		log.debug(ELog.message("resultSet is empty, returning status 404."));   
        		boolean passOnIfMissing = b.getAsString( "_passOnIfEmpty", "no" ).equals( "yes" );
				if (passOnIfMissing) throw new NotFoundException();
				return Response.status( Status.NOT_FOUND )
					.type( "text/plain" )
					.header( ACCESS_CONTROL_ALLOW_ORIGIN, "*" )
					.header( VARY, "Accept" )
					.entity( "404 Resource Not Found\n\n" + ru + "\n")
					.build()
					;
			}       	
        //
        	Map<String, String> termBindings = mpe.rename( resultsAndBindings.uriToShortnameMap );
            APIResultSet results = resultsAndBindings.resultSet.applyEdits( mpe );
			Bindings rc = new Bindings( resultsAndBindings.bindings.copy(), as );
		//	
        	if (_default.getPreferredSuffix().equals( r.getPreferredSuffix())) {
        		MediaType dmt = _default.getMediaType(rc);
        		if (!dmt.equals(r.getMediaType(rc))) {
        			r = RouterRestletSupport.changeMediaType( r, dmt );
        		}
        	}
        	
        	long expiresAt = nb.expiresAt;  
        	
//        	System.err.println( ">> expiresAt: " + RouterRestletSupport.expiresAtAsRFC1123(expiresAt));
//        	System.err.println( ">> expiresAt: (= " + expiresAt + ")" );
//        	System.err.println( ">>  " + (expiresAt < System.currentTimeMillis() ? " expired" : " still alive" ) + ".");
        	
        	String expiresDate = expiresAt < System.currentTimeMillis() 
        		? NO_EXPIRY 
        		: RouterRestletSupport.expiresAtAsRFC1123(expiresAt)
        		;
						
        	URI contentLocation = req.getURIwithFormat();
        	
			MediaType mt = r.getMediaType(rc);
			log.debug(ELog.message("rendering with formatter '%s'", mt ));
			Times times = c.times;
			Renderer.BytesOut bo = r.render( times, rc, termBindings, results );
			int mainHash = runHash + ru.toString().hashCode();
			return returnAs( contentLocation, expiresDate, results, mainHash + mt.hashCode(), wrap(times, bo), needsVaryAccept, mt );
	//
        } catch (StackOverflowError e) {
        	StatsValues.endpointException();
            log.error("Stack Overflow Error" );
            if (log.isDebugEnabled()) log.debug(ELog.message("%s", Messages.shortStackTrace( e ) ));
            String message = Messages.niceMessage("Stack overflow", e.getMessage() );
            return ErrorPages.respond(forErrorHandling, servCon, "stack_overflow", message, EldaException.SERVER_ERROR);
        
        } catch (VelocityRenderingException e) {
            return ErrorPages.respond(forErrorHandling, servCon, "velocity_rendering", e.getMessage(), EldaException.SERVER_ERROR); 
        
        } catch (BadRequestException e) {
        	return ErrorPages.respond(forErrorHandling, servCon, "bad_request", e.getMessage(), EldaException.BAD_REQUEST);
                    	
        } catch (UnknownShortnameException e) {
        	log.error(ELog.message("UnknownShortnameException: " + e.getMessage()));
            if (log.isDebugEnabled()) log.debug(ELog.message("%s", Messages.shortStackTrace( e )));
        	StatsValues.endpointException();
        	return ErrorPages.respond(forErrorHandling, servCon, "unknown_shortname", e.getMessage(), EldaException.BAD_REQUEST); 
        
        } catch (EldaException e) {
        	StatsValues.endpointException();
        	log.error(ELog.message("Exception: " + e.getMessage()));
        	if (log.isDebugEnabled()) log.debug(ELog.message("%s", Messages.shortStackTrace( e )));
        	return ErrorPages.respond(forErrorHandling, servCon, "exception", e.getMessage(), EldaException.SERVER_ERROR);
        
        } catch (NotFoundException e) {